// window.ailin_base64 = {
//     base64EncodeChars: "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/",
//     base64DecodeChars: new Array(
//         -1,
//         -1,
//         -1,
//         -1,
//         -1,
//         -1,
//         -1,
//         -1,
//         -1,
//         -1,
//         -1,
//         -1,
//         -1,
//         -1,
//         -1,
//         -1,
//         -1,
//         -1,
//         -1,
//         -1,
//         -1,
//         -1,
//         -1,
//         -1,
//         -1,
//         -1,
//         -1,
//         -1,
//         -1,
//         -1,
//         -1,
//         -1,
//         -1,
//         -1,
//         -1,
//         -1,
//         -1,
//         -1,
//         -1,
//         -1,
//         -1,
//         -1,
//         -1,
//         62,
//         -1,
//         -1,
//         -1,
//         63,
//         52,
//         53,
//         54,
//         55,
//         56,
//         57,
//         58,
//         59,
//         60,
//         61,
//         -1,
//         -1,
//         -1,
//         -1,
//         -1,
//         -1,
//         -1,
//         0,
//         1,
//         2,
//         3,
//         4,
//         5,
//         6,
//         7,
//         8,
//         9,
//         10,
//         11,
//         12,
//         13,
//         14,
//         15,
//         16,
//         17,
//         18,
//         19,
//         20,
//         21,
//         22,
//         23,
//         24,
//         25,
//         -1,
//         -1,
//         -1,
//         -1,
//         -1,
//         -1,
//         26,
//         27,
//         28,
//         29,
//         30,
//         31,
//         32,
//         33,
//         34,
//         35,
//         36,
//         37,
//         38,
//         39,
//         40,
//         41,
//         42,
//         43,
//         44,
//         45,
//         46,
//         47,
//         48,
//         49,
//         50,
//         51,
//         -1,
//         -1,
//         -1,
//         -1,
//         -1
//     ),
//     base64encode: function (e) {
//         var t;
//         var o;
//         var i;
//         var n;
//         var a;
//         var s;
//         i = e.length;
//         o = 0;
//         for (t = ""; o < i; ) {
//             n = 255 & e.charCodeAt(o++);
//             if (o == i) {
//                 t += ailin_base64.base64EncodeChars.charAt(n >> 2);
//                 t += ailin_base64.base64EncodeChars.charAt((3 & n) << 4);
//                 t += "==";
//                 break;
//             }
//             a = e.charCodeAt(o++);
//             if (o == i) {
//                 t += ailin_base64.base64EncodeChars.charAt(n >> 2);
//                 t += ailin_base64.base64EncodeChars.charAt(((3 & n) << 4) | ((240 & a) >> 4));
//                 t += ailin_base64.base64EncodeChars.charAt((15 & a) << 2);
//                 t += "=";
//                 break;
//             }
//             s = e.charCodeAt(o++);
//             t += ailin_base64.base64EncodeChars.charAt(n >> 2);
//             t += ailin_base64.base64EncodeChars.charAt(((3 & n) << 4) | ((240 & a) >> 4));
//             t += ailin_base64.base64EncodeChars.charAt(((15 & a) << 2) | ((192 & s) >> 6));
//             t += ailin_base64.base64EncodeChars.charAt(63 & s);
//         }
//         return t;
//     },
//     base64decode: function (e) {
//         var t;
//         var o;
//         var i;
//         var n;
//         var a;
//         var s;
//         var r;
//         s = e.length;
//         a = 0;
//         for (r = ""; a < s; ) {
//             do {
//                 t = ailin_base64.base64DecodeChars[255 & e.charCodeAt(a++)];
//             } while (a < s && -1 == t);
//             if (-1 == t) {
//                 break;
//             }
//             do {
//                 o = ailin_base64.base64DecodeChars[255 & e.charCodeAt(a++)];
//             } while (a < s && -1 == o);
//             if (-1 == o) {
//                 break;
//             }
//             r += String.fromCharCode((t << 2) | ((48 & o) >> 4));
//             do {
//                 if (61 == (i = 255 & e.charCodeAt(a++))) {
//                     return r;
//                 }
//                 i = ailin_base64.base64DecodeChars[i];
//             } while (a < s && -1 == i);
//             if (-1 == i) {
//                 break;
//             }
//             r += String.fromCharCode(((15 & o) << 4) | ((60 & i) >> 2));
//             do {
//                 if (61 == (n = 255 & e.charCodeAt(a++))) {
//                     return r;
//                 }
//                 n = ailin_base64.base64DecodeChars[n];
//             } while (a < s && -1 == n);
//             if (-1 == n) {
//                 break;
//             }
//             r += String.fromCharCode(((3 & i) << 6) | n);
//         }
//         return r;
//     },
//     utf16to8: function (e) {
//         var t;
//         var o;
//         var i;
//         var n;
//         t = "";
//         i = e.length;
//         for (o = 0; o < i; o++) {
//             (n = e.charCodeAt(o)) >= 1 && n <= 127
//                 ? (t += e.charAt(o))
//                 : n > 2047
//                 ? ((t += String.fromCharCode(224 | ((n >> 12) & 15))),
//                   (t += String.fromCharCode(128 | ((n >> 6) & 63))),
//                   (t += String.fromCharCode(128 | ((n >> 0) & 63))))
//                 : ((t += String.fromCharCode(192 | ((n >> 6) & 31))),
//                   (t += String.fromCharCode(128 | ((n >> 0) & 63))));
//         }
//         return t;
//     },
//     utf8to16: function (e) {
//         var t;
//         var o;
//         var i;
//         var n;
//         var a;
//         var s;
//         t = "";
//         i = e.length;
//         for (o = 0; o < i; ) {
//             switch ((n = e.charCodeAt(o++)) >> 4) {
//                 case 0:
//                 case 1:
//                 case 2:
//                 case 3:
//                 case 4:
//                 case 5:
//                 case 6:
//                 case 7:
//                     t += e.charAt(o - 1);
//                     break;
//                 case 12:
//                 case 13:
//                     a = e.charCodeAt(o++);
//                     t += String.fromCharCode(((31 & n) << 6) | (63 & a));
//                     break;
//                 case 14:
//                     a = e.charCodeAt(o++);
//                     s = e.charCodeAt(o++);
//                     t += String.fromCharCode(((15 & n) << 12) | ((63 & a) << 6) | ((63 & s) << 0));
//             }
//         }
//         return t;
//     },
//     encode: function (e) {
//         return ailin_base64.base64encode(ailin_base64.utf16to8(e));
//     },
//     decode: function (e) {
//         return ailin_base64.utf8to16(ailin_base64.base64decode(e));
//     }
// };
// module.exports = ailin_base64;


/**
 * Base64 编码和解码工具
 */
window.ailin_base64 = {
    base64EncodeChars: "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/",
    base64DecodeChars: [
        -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
        -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
        -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, 62,-1,-1,-1, 63,
        52, 53, 54, 55, 56, 57, 58, 59, 60, 61,-1,-1,-1,-1,-1,-1,
        -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11,12,13,14,
        15,16,17,18,19,20,21,22,23,24,25,-1,-1,-1,-1,-1,
        -1,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,
        41,42,43,44,45,46,47,48,49,50,51,-1,-1,-1,-1,-1
    ],

    /**
     * Base64 编码
     * @param {string} input - 要编码的字符串
     * @returns {string} - 编码后的 Base64 字符串
     */
    base64encode: function (input) {
        let output = '';
        let length = input.length;
        let index = 0;

        while (index < length) {
            let c1 = input.charCodeAt(index++) & 0xff;
            if (index === length) {
                output += this.base64EncodeChars.charAt(c1 >> 2);
                output += this.base64EncodeChars.charAt((c1 & 0x3) << 4);
                output += '==';
                break;
            }
            let c2 = input.charCodeAt(index++);
            if (index === length) {
                output += this.base64EncodeChars.charAt(c1 >> 2);
                output += this.base64EncodeChars.charAt(((c1 & 0x3) << 4) | ((c2 & 0xf0) >> 4));
                output += this.base64EncodeChars.charAt((c2 & 0xf) << 2);
                output += '=';
                break;
            }
            let c3 = input.charCodeAt(index++);
            output += this.base64EncodeChars.charAt(c1 >> 2);
            output += this.base64EncodeChars.charAt(((c1 & 0x3) << 4) | ((c2 & 0xf0) >> 4));
            output += this.base64EncodeChars.charAt(((c2 & 0xf) << 2) | ((c3 & 0xc0) >> 6));
            output += this.base64EncodeChars.charAt(c3 & 0x3f);
        }
        return output;
    },

    /**
     * Base64 解码
     * @param {string} input - 要解码的 Base64 字符串
     * @returns {string} - 解码后的字符串
     */
    base64decode: function (input) {
        let output = '';
        let length = input.length;
        let index = 0;

        while (index < length) {
            let c1;
            do {
                c1 = this.base64DecodeChars[input.charCodeAt(index++) & 0xff];
            } while (index < length && c1 === -1);
            if (c1 === -1) break;

            let c2;
            do {
                c2 = this.base64DecodeChars[input.charCodeAt(index++) & 0xff];
            } while (index < length && c2 === -1);
            if (c2 === -1) break;

            output += String.fromCharCode((c1 << 2) | ((c2 & 0x30) >> 4));

            let c3;
            do {
                if ((c3 = input.charCodeAt(index++) & 0xff) === 61) return output;
                c3 = this.base64DecodeChars[c3];
            } while (index < length && c3 === -1);
            if (c3 === -1) break;

            output += String.fromCharCode(((c2 & 0xf) << 4) | ((c3 & 0x3c) >> 2));

            let c4;
            do {
                if ((c4 = input.charCodeAt(index++) & 0xff) === 61) return output;
                c4 = this.base64DecodeChars[c4];
            } while (index < length && c4 === -1);
            if (c4 === -1) break;

            output += String.fromCharCode(((c3 & 0x3) << 6) | c4);
        }
        return output;
    },

    /**
     * UTF-16 转 UTF-8
     * @param {string} input - 要转换的 UTF-16 字符串
     * @returns {string} - 转换后的 UTF-8 字符串
     */
    utf16to8: function (input) {
        let output = '';
        let length = input.length;

        for (let index = 0; index < length; index++) {
            let char = input.charCodeAt(index);
            if (char >= 1 && char <= 127) {
                output += input.charAt(index);
            } else if (char > 2047) {
                output += String.fromCharCode(224 | ((char >> 12) & 15));
                output += String.fromCharCode(128 | ((char >> 6) & 63));
                output += String.fromCharCode(128 | (char & 63));
            } else {
                output += String.fromCharCode(192 | ((char >> 6) & 31));
                output += String.fromCharCode(128 | (char & 63));
            }
        }
        return output;
    },

    /**
     * UTF-8 转 UTF-16
     * @param {string} input - 要转换的 UTF-8 字符串
     * @returns {string} - 转换后的 UTF-16 字符串
     */
    utf8to16: function (input) {
        let output = '';
        let length = input.length;
        let index = 0;

        while (index < length) {
            let char = input.charCodeAt(index++);
            switch (char >> 4) {
                case 0:
                case 1:
                case 2:
                case 3:
                case 4:
                case 5:
                case 6:
                case 7:
                    output += input.charAt(index - 1);
                    break;
                case 12:
                case 13:
                    let char2 = input.charCodeAt(index++);
                    output += String.fromCharCode(((char & 0x1f) << 6) | (char2 & 0x3f));
                    break;
                case 14:
                    let char3 = input.charCodeAt(index++);
                    let char4 = input.charCodeAt(index++);
                    output += String.fromCharCode(((char & 0x0f) << 12) | ((char3 & 0x3f) << 6) | (char4 & 0x3f));
                    break;
            }
        }
        return output;
    },

    /**
     * 编码字符串
     * @param {string} input - 要编码的字符串
     * @returns {string} - 编码后的字符串
     */
    encode: function (input) {
        return this.base64encode(this.utf16to8(input));
    },

    /**
     * 解码字符串
     * @param {string} input - 要解码的字符串
     * @returns {string} - 解码后的字符串
     */
    decode: function (input) {
        return this.utf8to16(this.base64decode(input));
    }
};

module.exports = ailin_base64;
